# -*- coding: utf-8 -*-
"""
Created on Thu Feb 07 21:28:04 2013

@author: nzhao
"""
import operator
import numpy as np
from traits.api import HasTraits, Int, Array, Str, Bool, Float
from traitsui.api import View, Item, Group, HGroup, VGroup, RangeEditor

MAX_COL_NUM = 12

class MatViewer(HasTraits):
    nrow = Int
    ncol = Int
    mat  = Array
    realQ = Bool()
    rsymQ = Bool()
    hermiteQ = Bool()
    nonZero  = Int()
    sparRatio= Float()
    init_col = Int(0)

    def __init__(self, mat=[[0.0]]):
        try:
            self.mat = np.array(mat)
        except:
            print "array"
            
        self.nrow, self.ncol = mat.shape
        
        element_real = [type(x) is np.float64 for x in np.reshape(mat, self.nrow * self.ncol)]
        self.realQ = reduce(operator.and_, element_real, True)
        
        self.rsymQ = (self.mat.T == self.mat).all()
        
        self.hermiteQ = ((self.mat.T).conj() == self.mat).all()
        self.nonZero = np.count_nonzero(self.mat)
        self.sparRatio = 1.0 * self.nonZero / self.ncol / self.nrow
        
        self.add_elements()
        self.set_elements()
    
    def add_elements(self):
        for i in range(self.nrow):
            for j in range(min(MAX_COL_NUM, self.ncol)):
                self.add_trait('mat'+str(i)+str(j), Str() )
    
    def set_elements(self):
        for i in range(self.nrow):
            for j in range(min(MAX_COL_NUM, self.ncol)):
                val = self.mat[i][self.init_col+j]
                if abs(val) == 0.0:
                    str_val = '0.0'
                elif type(val) is np.complex128:
                    if val.imag > 0.0:
                        str_val = '%.2f + %.2f j'%(val.real, val.imag)
                    elif val.imag == 0.0:
                        str_val = '%.2f'%val.real
                    else:
                        str_val = '%.2f - %.2f j'%(val.real, abs(val.imag))
                elif type(val) is np.float64:
                    str_val = '%.2f'%val
                eval( 'self.set(' +'mat'+str(i)+str(j) + '="' + str_val + '")' )
    
    def _init_col_changed(self):
        self.set_elements()
                
    def default_traits_view(self):
        mat_view_content = [HGroup() for i in range(self.nrow)]

        for i in range(self.nrow):
            mat_view_content[i].content = [
                Item('mat'+str(i)+str(j), 
                     show_label=False, 
                     tooltip='row:'+str(i)+' col:'+str(self.init_col+j)+'\nval: '+str(self.mat[i][j]), style='readonly', width = 100
                     ) 
                     for j in range(min(MAX_COL_NUM, self.ncol))]
        mat_view = VGroup(content=mat_view_content, scrollable=True)
        v=View(height =0.9, width=0.9, resizable = True)
        v.content =Group(Group(
            HGroup(Item('nrow', style='readonly', label='row # '), 
                   Item('ncol', style='readonly', label='col # '),
                    Item('realQ', style='readonly', label='RealQ '),
                    Item('rsymQ', style='readonly', label='symQ '),
                    Item('hermiteQ', style='readonly', label='HermiteQ '),
                    Item('init_col', editor=RangeEditor(low = 0, 
                                                        high = max(0, self.ncol - MAX_COL_NUM), 
                                                        mode = 'spinner' )),
                    Item('nonZero', style='readonly', label='nonZero (#/ ' + str(self.ncol*self.nrow)+') '),
                    Item('sparRatio', style='readonly', label='ratio ='),
                    ), 
            mat_view)
            )
        return v
        
if __name__=='__main__':
    mv = MatViewer(np.array([[1,2,4.+1j],[2,3,4],[4.-1j,4,5]]))
    mv.configure_traits()
